﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Xml;

namespace SPVisualDev
{

    public partial class UCSPExplorer : UserControl
    {
        private string m_home_url = "http://localhost";


        //public event TreeNodeSelectedEventHandler NodeSelected;

        public UCSPExplorer()
        {
            InitializeComponent();

            tvwSPExplorer.BeforeExpand += new TreeViewCancelEventHandler(tvwSPExplorer_BeforeExpand);
        }

        public TreeView SPExplorer
        {
            get { return tvwSPExplorer; }
        }

        public string RootUrl
        {
            get
            {
                return m_home_url;
            }
            set
            {
                m_home_url = value;
            }
        }

        public string SelectedUrl
        {
            get
            {
                if (tvwSPExplorer.SelectedNode != null)
                    return tvwSPExplorer.SelectedNode.Name;
                else
                    return string.Empty;
            }
        }

        public string GetContentTypeDataForWOW64()
        {
            if (tvwSPExplorer.SelectedNode != null)
            {
                if (tvwSPExplorer.SelectedNode.Tag is TreeNodeType)
                {
                    TreeNodeType type = (TreeNodeType)tvwSPExplorer.SelectedNode.Tag;

                    if (type == TreeNodeType.ContentType)
                    {
                        string url;
                        if (ShowContentTypeGroups)
                            url = tvwSPExplorer.SelectedNode.Parent.Parent.Parent.Name;
                        else
                            url = tvwSPExplorer.SelectedNode.Parent.Parent.Name;

                        string output;
                        int err = StsAdmCommands.ExecuteStsadmCommand("getcontenttypedata", "-url \"" + url + "\" -name \"" + tvwSPExplorer.SelectedNode.Text + "\"", out output);
                        if (err == 0)
                        {
                            return output;
                        }
                        else
                        {
                            throw new Exception("Error occured. " + output);
                        }
                    }
                }


            }

            return null;
        }

        public string SelectedContentTypeId
        {
            get
            {
                if (tvwSPExplorer.SelectedNode != null)
                {
                    if (tvwSPExplorer.SelectedNode.Tag is TreeNodeType)
                    {
                        TreeNodeType type = (TreeNodeType)tvwSPExplorer.SelectedNode.Tag;

                        if (type == TreeNodeType.ContentType)
                        {
                            return tvwSPExplorer.SelectedNode.Name;
                        }
                    }
                }

                return null;
            }
        }

        public SPContentType SelectedContentType
        {
            get
            {
                if (tvwSPExplorer.SelectedNode != null)
                {
                    if (tvwSPExplorer.SelectedNode.Tag is TreeNodeType)
                    {
                        TreeNodeType type = (TreeNodeType)tvwSPExplorer.SelectedNode.Tag;

                        if (type == TreeNodeType.ContentType)
                        {
                            string url;
                            if (ShowContentTypeGroups)
                                url = tvwSPExplorer.SelectedNode.Parent.Parent.Parent.Name;
                            else
                                url = tvwSPExplorer.SelectedNode.Parent.Parent.Name;

                            using (SPSite site = new SPSite(url))
                            {
                                using (SPWeb web = site.OpenWeb())
                                {
                                    return web.ContentTypes[tvwSPExplorer.SelectedNode.Text];
                                }
                            }
                        }

                    }
                }

                return null;
            }
        }

        public bool ShowSiteCollections = true;
        public bool ShowWebs = true;
        public bool ShowLists = true;
        public bool ShowListFolders = false;
        public bool ShowListItems = false;
        public bool ShowContentTypes = false;
        public bool ShowContentTypeGroups = false;
        public bool UseWOW64BitCompatibleMode = false;

        public void InitExplorer()
        {
            tvwSPExplorer.ShowPlusMinus = true;
            tvwSPExplorer.ImageList = imgSPExplorerImages;

            tvwSPExplorer.BeginUpdate();

            tvwSPExplorer.Nodes.Add("Local server (" + m_home_url + ")");
            tvwSPExplorer.Nodes[0].Name = string.Empty;
            tvwSPExplorer.Nodes[0].Tag = TreeNodeType.Root;
            tvwSPExplorer.Nodes[0].ImageKey = string.Empty;
            tvwSPExplorer.Nodes[0].SelectedImageKey = string.Empty;
            tvwSPExplorer.Nodes[0].Nodes.Add(string.Empty);
            tvwSPExplorer.EndUpdate();


            string img_lib = Common.GetSharePointInstallPath() + @"\TEMPLATE\IMAGES";

            Image img = Image.FromFile(img_lib + "\\XLM16.gif");
            imgSPExplorerImages.Images.Add("WebApplication", img);

            img = Image.FromFile(img_lib + "\\Cat.gif");
            imgSPExplorerImages.Images.Add("Site", img);

            img = Image.FromFile(img_lib + "\\STSICON.gif");
            imgSPExplorerImages.Images.Add("Web", img);

            img = Image.FromFile(img_lib + "\\sts_list16.gif");
            imgSPExplorerImages.Images.Add("List", img);

            img = Image.FromFile(img_lib + "\\folder16.gif");
            imgSPExplorerImages.Images.Add("Folder", img);

            img = Image.FromFile(img_lib + "\\CONTENT.gif");
            imgSPExplorerImages.Images.Add("ContentType", img);

            Application.DoEvents();
            tvwSPExplorer.Nodes[0].Expand();

        }

        public void RefreshNode(TreeNode n)
        {
            while (n.Nodes.Count > 0)
                n.Nodes.RemoveAt(0);

            RenderNode(n);
        }


        private void tvwSPExplorer_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            try
            {
                if (e.Action == TreeViewAction.Expand)
                    RenderNode(e.Node);
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private void GetAllWebApplications(TreeNode ParentNode)
        {
            if (UseWOW64BitCompatibleMode)
            {
                string output;
                int err = StsAdmCommands.ExecuteStsadmCommand("enumwebapplications", string.Empty, out output);
                if (err == 0)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(output);

                    foreach (XmlElement el in xmldoc.SelectSingleNode("/XmlRoot/WebApplications").ChildNodes)
                    {
                        TreeNode child = ParentNode.Nodes.Add(el.GetAttribute("Url"), string.IsNullOrEmpty(el.GetAttribute("Name")) ? el.GetAttribute("DefaultServerComment") : el.GetAttribute("DisplayName"));
                        child.Tag = (el.GetAttribute("Type") == "Admin") ? TreeNodeType.WebApplicationAdmin : TreeNodeType.WebApplication;
                        child.ImageKey = "WebApplication";
                        child.SelectedImageKey = "WebApplication";
                        child.Nodes.Add(string.Empty);
                    }
                }
                else
                {
                    throw new Exception("Error occured: ");
                }
            }
            else
            {
                foreach (SPWebApplication webapp in SPWebService.ContentService.WebApplications)
                {
                    TreeNode child = ParentNode.Nodes.Add(webapp.GetResponseUri(SPUrlZone.Default).ToString(), string.IsNullOrEmpty(webapp.Name) ? webapp.DefaultServerComment : webapp.DisplayName);
                    child.Tag = TreeNodeType.WebApplication;
                    child.ImageKey = "WebApplication";
                    child.SelectedImageKey = "WebApplication";
                    child.Nodes.Add(string.Empty);
                }

                foreach (SPWebApplication webapp in SPWebService.AdministrationService.WebApplications)
                {
                    TreeNode child = ParentNode.Nodes.Add(webapp.GetResponseUri(SPUrlZone.Default).ToString(), string.IsNullOrEmpty(webapp.Name) ? webapp.DefaultServerComment : webapp.DisplayName);
                    child.Tag = TreeNodeType.WebApplicationAdmin;
                    child.ImageKey = "WebApplication";
                    child.SelectedImageKey = "WebApplication";
                    child.Name = webapp.GetResponseUri(SPUrlZone.Default).ToString();
                    child.Nodes.Add(string.Empty);
                }

            }
        }

        private void GetAllTopLevelSites(TreeNode ParentNode, TreeNodeType Type, string Url)
        {
            if (UseWOW64BitCompatibleMode)
            {
                string output;
                int err = StsAdmCommands.ExecuteStsadmCommand("enumtoplevelsites", "-type \"" + Type.ToString() + "\" -url \"" + Url + "\"", out output);
                if (err == 0)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(output);

                    foreach (XmlElement el in xmldoc.SelectSingleNode("/XmlRoot/Sites").ChildNodes)
                    {
                        TreeNode child = ParentNode.Nodes.Add(el.GetAttribute("Url"), el.GetAttribute("Title"));
                        child.Tag = TreeNodeType.Site;
                        child.ImageKey = "Site";
                        child.SelectedImageKey = "Site";
                        child.Nodes.Add(string.Empty);
                    }
                }
                else
                {
                    throw new Exception("Error occured: ");
                }
            }
            else
            {
                SPWebApplication webapp = SPWebApplication.Lookup(new Uri(Url));
                foreach (SPSite site in webapp.Sites)
                {
                    try
                    {
                        TreeNode child = ParentNode.Nodes.Add(site.Url, site.RootWeb.Title);
                        child.Tag = TreeNodeType.Site;
                        child.ImageKey = "Site";
                        child.SelectedImageKey = "Site";
                        child.Nodes.Add(string.Empty);
                    }
                    finally
                    {
                        site.Close();
                    }
                }
            }
        }

        private void GetAllSubWebs(TreeNode ParentNode, string Url)
        {
            if (UseWOW64BitCompatibleMode)
            {
                string output;
                int err = StsAdmCommands.ExecuteStsadmCommand("enumsubwebs", "-url \"" + Url + "\"", out output);
                if (err == 0)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(output);

                    foreach (XmlElement el in xmldoc.SelectSingleNode("/XmlRoot/Webs").ChildNodes)
                    {
                        TreeNode child = ParentNode.Nodes.Add(el.GetAttribute("Url"), el.GetAttribute("Title"));
                        child.Tag = TreeNodeType.Web;
                        child.ImageKey = "Web";
                        child.SelectedImageKey = "Web";
                        child.Nodes.Add(string.Empty);
                    }
                }
                else
                {
                    throw new Exception("Error occured: ");
                }
            }
            else
            {
                using (SPSite site = new SPSite(Url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPWebCollection coll = web.Webs;
                        foreach (SPWeb w in coll)
                        {
                            try
                            {
                                if (w.IsRootWeb || w.ID == web.ID)
                                    continue;

                                TreeNode child = ParentNode.Nodes.Add(w.Url, w.Title);
                                child.Tag = TreeNodeType.Web;
                                child.ImageKey = "Web";
                                child.SelectedImageKey = "Web";
                                child.Nodes.Add(string.Empty);
                            }
                            finally
                            {
                                w.Close();
                            }
                        }
                    }
                }
            }
        }

        private void GetContentTypeGroups(TreeNode ParentNode, string Url)
        {
            if (UseWOW64BitCompatibleMode)
            {
                string output;
                int err = StsAdmCommands.ExecuteStsadmCommand("enumcontenttypegroups", "-url \"" + Url + "\"", out output);
                if (err == 0)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(output);

                    foreach (XmlElement el in xmldoc.SelectSingleNode("/XmlRoot/ContentTypeGroups").ChildNodes)
                    {
                        TreeNode child = ParentNode.Nodes.Add(el.GetAttribute("Name"), el.GetAttribute("Name"));
                        child.Tag = TreeNodeType.ContentTypeGroup;
                        child.ImageKey = "Folder";
                        child.SelectedImageKey = "Folder";
                        child.Nodes.Add(string.Empty);
                    }
                }
                else
                {
                    throw new Exception("Error occured: ");
                }
            }
            else
            {

                using (SPSite site = new SPSite(Url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPContentTypeCollection coll = web.ContentTypes;
                        List<string> list = new List<string>();

                        foreach (SPContentType ct in coll)
                        {
                            if (!list.Contains(ct.Group))
                                list.Add(ct.Group);
                        }

                        foreach (string s in list)
                        {
                            TreeNode child = ParentNode.Nodes.Add(s, s);
                            child.Tag = TreeNodeType.ContentTypeGroup;
                            child.ImageKey = "Folder";
                            child.SelectedImageKey = "Folder";
                            child.Nodes.Add(string.Empty);
                        }
                    }
                }
            }
        }

        private void GetContentTypes(TreeNode ParentNode, string Url, string Group)
        {
            if (UseWOW64BitCompatibleMode)
            {
                string output;
                int err = StsAdmCommands.ExecuteStsadmCommand("enumcontenttypesbygroup", "-url \"" + Url + "\" -group \"" + Group + "\"", out output);
                if (err == 0)
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(output);

                    foreach (XmlElement el in xmldoc.SelectSingleNode("/XmlRoot/ContentTypes").ChildNodes)
                    {
                        TreeNode child = ParentNode.Nodes.Add(el.GetAttribute("Id"), el.GetAttribute("Name"));
                        child.Tag = TreeNodeType.ContentType;
                        child.ImageKey = "ContentType";
                        child.SelectedImageKey = "ContentType";
                    }
                }
                else
                {
                    throw new Exception("Error occured: ");
                }
            }
            else
            {
                using (SPSite site = new SPSite(Url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {


                        SPContentTypeCollection coll = web.ContentTypes;
                        List<SPContentType> list = new List<SPContentType>();

                        foreach (SPContentType ct in coll)
                        {
                            if (ct.Group == Group && !list.Contains(ct))
                                list.Add(ct);
                        }

                        foreach (SPContentType ct in list)
                        {
                            TreeNode child = ParentNode.Nodes.Add(ct.Id.ToString(), ct.Name);
                            child.Tag = TreeNodeType.ContentType;
                            child.ImageKey = "ContentType";
                            child.SelectedImageKey = "ContentType";
                        }
                    }
                }
            }
        }

        private void RenderNode(TreeNode n)
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;

                TreeNodeType node_type = (TreeNodeType)n.Tag;

                if (n.Nodes.Count == 1)
                {
                    if (n.Nodes[0].Tag == null)
                        n.Nodes.RemoveAt(0);
                }

                if (n.Nodes.Count == 0)
                {
                    if (node_type == TreeNodeType.Root)
                    {
                        GetAllWebApplications(n);

                        return;
                    }

                    if ((node_type == TreeNodeType.WebApplication || node_type == TreeNodeType.WebApplicationAdmin) && ShowSiteCollections)
                    {
                        GetAllTopLevelSites(n, node_type, n.Name);

                        return;
                    }


                    TreeNode nearest_web_node = FindNearestWebNode(n);

                    string url = nearest_web_node.Name;


                    tvwSPExplorer.BeginUpdate();

                    try
                    {
                        if (ShowContentTypes && (node_type == TreeNodeType.Site || node_type == TreeNodeType.Web || node_type == TreeNodeType.ContentTypeFolder || node_type == TreeNodeType.ContentTypeGroup))
                        {
                            if (node_type == TreeNodeType.Site || node_type == TreeNodeType.Web)
                            {
                                TreeNode child = n.Nodes.Add("Content types");
                                child.Tag = TreeNodeType.ContentTypeFolder;
                                child.ImageKey = "Folder";
                                child.SelectedImageKey = "Folder";
                                child.Nodes.Add(string.Empty);

                            }
                            else if (node_type == TreeNodeType.ContentTypeFolder && ShowContentTypeGroups)
                            {
                                GetContentTypeGroups(n, url);
                            }
                            else if (node_type == TreeNodeType.ContentTypeGroup || node_type == TreeNodeType.ContentTypeFolder)
                            {
                                GetContentTypes(n, url, n.Name);
                            }

                        }

                        if (ShowWebs && (node_type == TreeNodeType.Site || node_type == TreeNodeType.Web))
                        {
                            GetAllSubWebs(n, url);
                        }
                    }
                    finally
                    {
                        tvwSPExplorer.EndUpdate();
                    }

                    /*
                    using (SPSite site = new SPSite(url))
                    {
                        using (SPWeb web = site.OpenWeb())
                        {
                            tvwSPExplorer.BeginUpdate();

                            try
                            {

                                if (ShowContentTypes && (node_type == TreeNodeType.Site || node_type == TreeNodeType.ContentTypeGroup))
                                {
                                    if (node_type == TreeNodeType.Site && ShowContentTypeGroups)
                                    {
                                        SPContentTypeCollection coll = web.ContentTypes;
                                        Hashtable ht = new Hashtable();

                                        foreach (SPContentType ct in coll)
                                        {
                                            if (!ht.ContainsKey(ct.Group))
                                                ht.Add(ct.Group, TreeNodeType.ContentTypeGroup);
                                        }

                                        foreach (DictionaryEntry de in ht)
                                        {
                                            TreeNode child = n.Nodes.Add(de.Key.ToString(), de.Key.ToString());
                                            child.Tag = de.Value;
                                            child.ImageKey = "ContentType";
                                            child.SelectedImageKey = "ContentType";
                                            child.Nodes.Add(string.Empty);
                                        }
                                    }
                                    else if (node_type == TreeNodeType.ContentTypeGroup || node_type == TreeNodeType.Site)
                                    {
                                        SPContentTypeCollection coll = web.ContentTypes;
                                        foreach (SPContentType ct in coll)
                                        {

                                            if (node_type == TreeNodeType.ContentTypeGroup && n.Name != ct.Group)
                                                continue;

                                            TreeNode child = n.Nodes.Add(ct.Id.ToString(), ct.Name);
                                            child.Tag = TreeNodeType.ContentType;
                                            child.ImageKey = "ContentType";
                                            child.SelectedImageKey = "ContentType";
                                        }
                                    }
                                }

                                if (ShowLists && (node_type == TreeNodeType.Site || node_type == TreeNodeType.Web))
                                {
                                    web.Lists.ListsForCurrentUser = true;
                                    SPListCollection coll = web.Lists;

                                    foreach (SPList list in coll)
                                    {
                                        TreeNode child = n.Nodes.Add(web.Url + "/" + list.RootFolder.Url, list.Title);
                                        child.Tag = TreeNodeType.List;
                                        child.ImageKey = "List";
                                        child.SelectedImageKey = "List";
                                        child.Nodes.Add(string.Empty);
                                    }
                                }

                                if (ShowListFolders && (node_type == TreeNodeType.List || node_type == TreeNodeType.Folder))
                                {
                                    SPFolder parent_folder = web.GetFolder(n.Name);
                                    SPFolderCollection coll = parent_folder.SubFolders;
                                    foreach (SPFolder folder in coll)
                                    {
                                        TreeNode child = n.Nodes.Add(web.Url + "/" + folder.Url, folder.Name);
                                        child.Tag = TreeNodeType.Folder;
                                        child.ImageKey = "Folder";
                                        child.SelectedImageKey = "Folder";
                                        child.Nodes.Add(string.Empty);
                                    }

                                }
                            }
                            finally
                            {
                                tvwSPExplorer.EndUpdate();
                            }
                        }
                    }*/
                }
            }
            catch (Exception ex)
            {
                this.Cursor = Cursors.Default;
                MessageBox.Show("Error occured: " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private TreeNode FindNearestWebNode(TreeNode CurrentNode)
        {
            while ((TreeNodeType)CurrentNode.Tag != TreeNodeType.Web && (TreeNodeType)CurrentNode.Tag != TreeNodeType.Site && CurrentNode != tvwSPExplorer.TopNode)
                CurrentNode = CurrentNode.Parent;

            return CurrentNode;
        }


    }



    public enum TreeNodeType
    {
        Root,
        Site,
        Web,
        List,
        Folder,
        File,
        ContentTypeFolder,
        ContentType,
        ContentTypeGroup,
        WebApplication,
        WebApplicationAdmin
    }
}
